//网页串口相关函数
var MixlyWebSerial = {};

MixlyWebSerial.opened = false;
MixlyWebSerial.dataUpdate = null;
MixlyWebSerial.serialReceive = "";
MixlyWebSerial.restString = "";
MixlyWebSerial.deviceObj = null;
MixlyWebSerial.transport = null;
MixlyWebSerial.target = null;

MixlyWebSerial.restStr = "";

MixlyWebSerial.openTool = function () {
	layui.use(['layer', 'element', 'form'], function () {
		var layer = layui.layer;
		var element = layui.element;
		var form = layui.form;
		var serial_com_update = null;
		element.on('tab(serial)', function (elem) {
			if (elem.index == 1) {
				MixlyCharts.init();
			} else {
				try {
					MixlyCharts.chart && MixlyCharts.chart.destroy();
				} catch (e) {
					//console.log(e);
				}
				MixlyCharts.draw && clearInterval(MixlyCharts.draw);
				MixlyCharts.addData && clearInterval(MixlyCharts.addData);
			}
		});

		form.on('checkbox', function (data) {
			if (data.elem.id == "set_dtr" || data.elem.id == "set_rts") {
				MixlyWebSerial.setDtrAndRts();
			} else if (data.elem.id == "send_serial_data_type") {
				if (data.elem.checked) {
					$("#serial_write").attr("placeholder", "请输入内容");
				} else {
					$("#serial_write").attr("placeholder", "请输入内容  例如:0x03 0x04");
				}
			}
		});

		var layer = layui.layer;
		layer.open({
			type: 1,
			id: "serial_page",
			title: false,
			area: ["90%", "80%"],
			closeBtn: 1,
			resize: true,
			fixed: true,
			move: $('#serial-move'),
			content: $('#serial-form'),
			success: function (layero, index) {
				try {
                    var now_page = document.getElementById(layero.selector.replace("#", ""));
                    now_page.style.minWidth = "600px";
                    now_page.style.minHeight = "250px";
                    now_page.style.maxWidth = "710px";
                    now_page.style.maxHeight = "500px";
                    var now_height = document.documentElement.clientHeight;
                    var now_width = document.documentElement.clientWidth;
                    now_page.style.left = (now_width - now_page.clientWidth) / 2 + "px";
                    now_page.style.top = (now_height - now_page.clientHeight) / 2 + "px";
                    now_page.style.borderRadius = "8px";
                } catch (e) {
                    console.log(e);
                }

                var serialPage = document.getElementById("serial_page");
                serialPage.style.overflow = "hidden";
                serialPage.style.maxWidth = "710px";
                serialPage.style.maxHeight = "500px";
                serialPage.style.minWidth = "600px";
                serialPage.style.minHeight = "250px";
                serialPage.style.borderRadius = "8px";

                layero[0].childNodes[1].childNodes[0].classList.remove('layui-layer-close2');
                layero[0].childNodes[1].childNodes[0].classList.add('layui-layer-close1');

				MixlyStatusBar.show(1);
            	MixlyWebSerial.opened = true;
			},
			end: function () {
				MixlyCharts.draw && clearInterval(MixlyCharts.draw);
				MixlyCharts.addData && clearInterval(MixlyCharts.addData);
				document.getElementById('serial-form').style.display = 'none';
				MixlyStatusBar.setValue($("#serial_content").val(), true);
				try {
					MixlyCharts.chart && MixlyCharts.chart.destroy();
				} catch (e) {
					//console.log(e);
				}
				//if (!espTool.connected()) {
				//	MixlyWebSerial.dataUpdate && clearInterval(MixlyWebSerial.dataUpdate);
				//}
				element.tabChange('serial', '1');
				MixlyWebSerial.opened = false;
			}
		});
	});
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.serialRead(MixlyWebSerial.deviceObj);
	} else {
		if (!espTool.connected()) {
			MixlyWebBU.clickConnect();
		}
	}
}

MixlyWebSerial.dataRefresh = async function () {
	if (espTool.connected() && !MixlyWebBU.burning && !MixlyWebBU.uploading) {
		try {
			var result = await espTool.read();
			MixlyWebSerial.receiveData = result;

			let disposeRead = MixlyWebSerial.receiveData.split(/[(\r\n)\r\n]+/);
			if (typeof disposeRead === "object" && disposeRead.length > 0) {
				disposeRead[0] = MixlyWebSerial.restStr + disposeRead[0];
				MixlyWebSerial.restStr = disposeRead.pop();
				for (let i = 0; i < disposeRead.length; i++) {
					MixlyCharts.addData(disposeRead[i]);
				}
			}

			var oldReceiveData = "";
			var disposeData = [];
			if (MixlyWebSerial.opened) {
				oldReceiveData = $("#serial_content").val();
			} else {
				oldReceiveData = MixlyStatusBar.getValue();
			}

			disposeData = oldReceiveData.split(/[(\r\n)\r\n]+/);

			if ($("#receive_serial_data_type")[0].checked == false) {
				MixlyWebSerial.receiveData = Uint8ArrayToString(stringToByte(MixlyWebSerial.receiveData));
				MixlyWebSerial.receiveData = MixlyWebSerial.receiveData.replace(/^\s*/, "");
			}

			oldReceiveData = "";
			if (disposeData.length >= 1000) {
				for (var z = disposeData.length - 1000; z < disposeData.length - 1; z++) {
					oldReceiveData += disposeData[z] + "\n";
				}
			} else {
				for (var z = 0; z < disposeData.length - 1; z++) {
					oldReceiveData += disposeData[z] + "\n";
				}
			}
			oldReceiveData += disposeData[disposeData.length - 1];
			if (MixlyWebSerial.opened) {
				$("#serial_content").val(oldReceiveData + MixlyWebSerial.receiveData);
				$("#screen_scroll")[0].checked == true && $("#serial_content").scrollTop($("#serial_content")[0].scrollHeight);
			} else {
				if (oldReceiveData + MixlyWebSerial.receiveData == "\n") {
					MixlyStatusBar.setValue('', true);
				} else {
					MixlyStatusBar.setValue(oldReceiveData + MixlyWebSerial.receiveData, true);
				}
			}
			MixlyWebSerial.receiveData = "";
		} catch (e) {
		}
	}
}

MixlyWebSerial.connectCom = function () {
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.selectDevice();
	} else {
		MixlyWebBU.clickConnect();
	}
	MixlyStatusBar.show(1);
}

/**
* @ function 串口发送
* @ description 串口发送Ctrl + C
* @ return void
*/
MixlyWebSerial.writeCtrlC = async function () {
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.target.serialWrite('\x03').then(function () {
			return MixlyWebSerial.target.serialWrite('\x0D');
		}).then(function () {
			return MixlyWebSerial.target.serialWrite('\x0A');
		});
	} else {
		if (espTool.connected()) {
			var serialArray = [3, 13, 10];
			var arrayBuffer = new Int8Array(serialArray).buffer;
			await espTool.writeArrayBuffer(arrayBuffer);
		}
	}
}

/**
* @ function 串口发送
* @ description 串口发送Ctrl + D
* @ return void
*/
MixlyWebSerial.writeCtrlD = async function () {
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.target.serialWrite('\x03').then(function () {
			return MixlyWebSerial.target.serialWrite('\x04');
		});
	} else {
		if (espTool.connected()) {
			var serialArray = [3, 4];
			var arrayBuffer = new Int8Array(serialArray).buffer;
			await espTool.writeArrayBuffer(arrayBuffer);
		}
	}
}

/**
* @ function 读取串口发送框数据并发送
* @ description 读取串口发送框数据并发送，然后清空串口发送框
* @ return void
*/
MixlyWebSerial.write = async function () {
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.serialWrite();
	} else {
		if (espTool.connected()) {
			if ($("#send_serial_data_type")[0].checked == false) {
				var ready_send_data = $("#serial_write").val();
				var string_send_hex = ready_send_data.trim().split(/\s+/);
				var num_send_hex = [];
				for (var i = 0; i < string_send_hex.length; i++) {
					if (parseInt(string_send_hex[i], 16))
						num_send_hex.push(parseInt(string_send_hex[i], 16));
				}
				espTool.writeArrayBuffer(num_send_hex);
				var ready_send_data_end = $('#send_data_with option:selected').val();
				ready_send_data_end = ready_send_data_end.replace("\\r", "\r");
				ready_send_data_end = ready_send_data_end.replace("\\n", "\n");
				if (ready_send_data_end == "no") {
					ready_send_data_end = "";
				}
				if (ready_send_data) {
					espTool.write(ready_send_data_end);
					$("#serial_write").val("");
				}
			} else {
				var ready_send_data = $("#serial_write").val();
				var ready_send_data_end = $('#send_data_with option:selected').val();
				ready_send_data_end = ready_send_data_end.replace("\\r", "\r");
				ready_send_data_end = ready_send_data_end.replace("\\n", "\n");
				if (ready_send_data_end == "no") {
					ready_send_data_end = "";
				}
				if (ready_send_data) {
					await espTool.write(ready_send_data + ready_send_data_end);
					$("#serial_write").val("");
				}
			}
		}
	}
}

/**
* @ function 读取串口发送框数据并发送字符串
* @ description 读取串口发送框数据并发送字符串，然后清空串口发送框
* @ return void
*/
MixlyWebSerial.writeString = async function () {
	if (MixlyBU.uploadFileType == "hex") {
		MixlyWebSerial.serialWrite();
	} else {
		if (espTool.connected()) {
			var ready_send_data = $("#serial_write_string").val();
			var ready_send_data_end = $('#send_string_data_with option:selected').val();
			ready_send_data_end = ready_send_data_end.replace("\\r", "\r");
			ready_send_data_end = ready_send_data_end.replace("\\n", "\n");
			if (ready_send_data_end == "no") {
				ready_send_data_end = "";
			}
			if (ready_send_data) {
				await espTool.write(ready_send_data + ready_send_data_end);
				$("#serial_write_string").val("");
			}
		}
	}
}

/**
* @ function 清空串口输出框
* @ description 清空当前串口输出框中的数据
* @ return void
*/
MixlyWebSerial.clearContent = function () {
	document.getElementById('serial_content').value = '';
}

// Choose a device
MixlyWebSerial.selectDevice = async () => {
	// setStatus("Selecting device...");
	// setTransfer();
	try {
		const device = await navigator.usb.requestDevice({
			filters: [{ vendorId: 0xD28 }]
		});
		MixlyWebSerial.deviceObj = device;
		MixlyWebSerial.transport = new DAPjs.WebUSB(MixlyWebSerial.deviceObj);
		MixlyWebSerial.target = new DAPjs.DAPLink(MixlyWebSerial.transport);
		await MixlyWebSerial.target.connect();
		await MixlyWebSerial.target.setSerialBaudrate(115200);
		MixlyWebSerial.serialRead();
		return true;
	} catch (error) {
		MixlyWebSerial.setStatus(error);
		MixlyWebSerial.target = null;
		MixlyWebBU.toggleUIToolbar(false);
		return false;
	}
}

MixlyWebSerial.buildTarget = async () => {
	if (MixlyWebSerial.target && MixlyWebSerial.target.transport) {
		return;
	}
	else {
		if (!MixlyWebSerial.deviceObj) {
			modalAlert('无可用设备!');
			return;
		}
		else {
			MixlyWebSerial.transport = new DAPjs.WebUSB(MixlyWebSerial.deviceObj);
			MixlyWebSerial.target = new DAPjs.DAPLink(MixlyWebSerial.transport);
			await MixlyWebSerial.target.connect();
			await MixlyWebSerial.target.setSerialBaudrate(115200);
		}
	}
}

//-----------------------------------------------------------
MixlyWebSerial.setStatus = state => {
	alert(state);
}

MixlyWebSerial.setTransfer = progress => {

}

// Update a device with the firmware image transferred from block/code
MixlyWebSerial.update = async () => {
	if (!MixlyWebSerial.target) {
		if (!await MixlyWebSerial.selectDevice()) {
			MixlyStatusBar.setValue("", true);
			$("#serial_content").val("");
			return;
		}
	}
	let buffer = null;
	var hex2Blob = new Blob([MixlyFile.getHex()], { type: 'text/plain' });
	buffer = await hex2Blob.arrayBuffer()
	if (!buffer) return;

	MixlyWebSerial.target.on(DAPjs.DAPLink.EVENT_PROGRESS, progress => {
		MixlyWebSerial.setTransfer(progress);
	});

	try {
		// Push binary to board
		// setStatus(`Flashing binary file ${buffer.byteLength} words long...`);
		await MixlyWebSerial.target.connect();
		await MixlyWebSerial.target.setSerialBaudrate(115200);
		layui.use('layer', function () {
			var layer = layui.layer;
			layer.open({
				type: 1,
				title: '上传',
				content: $('#webusb-flashing'),
				closeBtn: 0,
				end: async function () {
					try {
						await MixlyWebSerial.target.disconnect();
					} catch (e) {
						console.log(e);
					}
				}
			});
		});
		await MixlyWebSerial.target.flash(buffer);
		layer.closeAll('page');
		await MixlyWebSerial.target.disconnect();
		//await MixlyWebSerial.target.connect();
		// MixlyWebSerial.setStatus("Flash complete!");
	} catch (error) {
		MixlyWebSerial.setStatus(error);
		layer.closeAll('page');
		MixlyWebSerial.target = null;
	}
	MixlyWebBU.toggleUIToolbar(false);
}

MixlyWebSerial.serialRead = async () => {
	if (!MixlyWebSerial.target) {
		MixlyWebSerial.selectDevice();
		MixlyStatusBar.setValue("", true);
		$("#serial_content").val("");
		return;
	}
	if (!MixlyWebSerial.target.connected) {
		try {
			await MixlyWebSerial.target.connect();
		}
		catch (e) {
			console.log(e);
		}
		MixlyStatusBar.setValue("", true);
		$("#serial_content").val("");
	}
	MixlyStatusBar.show(1);
	//防止重复绑定事件监听
	MixlyWebSerial.target.removeAllListeners(DAPjs.DAPLink.EVENT_SERIAL_DATA);
	MixlyWebSerial.target.on(DAPjs.DAPLink.EVENT_SERIAL_DATA, data => {
		if (MixlyWebSerial.opened) {
			serial_receive_old = $("#serial_content").val();
		} else {
			serial_receive_old = MixlyStatusBar.getValue();
		}
		if ($("#receive_serial_data_type")[0].checked == false) {
			data = Uint8ArrayToString(stringToByte(data));
			data = data.replace(/^\s*/, "");
			data += "\n";
		}
		if (MixlyWebSerial.opened) {
			$("#serial_content").val(serial_receive_old + data);
			$("#screen_scroll")[0].checked == true && $("#serial_content").scrollTop($("#serial_content")[0].scrollHeight);
			MixlyCharts.addData(data);
		} else {
			MixlyStatusBar.setValue(serial_receive_old + data, true);
		}

	});
	await MixlyWebSerial.target.startSerialRead(MixlyWebSerial.deviceObj);
}

MixlyWebSerial.serialWrite = async () => {
	if (!MixlyWebSerial.target.connected) {
		try {
			await MixlyWebSerial.target.connect();
		}
		catch (e) {
			console.error(e);
		}
	}
	if (await MixlyWebSerial.target.getSerialBaudrate() != 115200) {
		try {
			await MixlyWebSerial.target.setSerialBaudrate(115200);
		}
		catch (e) {
			console.error(e);
		}
	}
	var ready_send_data = $("#serial_write").val() || $("#serial_write_string").val();
	var ready_send_data_end = $('#send_string_data_with option:selected').val();
	ready_send_data_end = ready_send_data_end.replace("\\r", "\r");
	ready_send_data_end = ready_send_data_end.replace("\\n", "\n");
	if (ready_send_data_end == "no") {
		ready_send_data_end = "";
	}
	if (ready_send_data) {
		await MixlyWebSerial.target.serialWrite(ready_send_data + ready_send_data_end);
		$("#serial_write_string").val("");
		$("#serial_write").val("");
		//可能是因为mutex lock的原因，每次发送后需要重新启动监听，并且清理缓冲区
		await MixlyWebSerial.target.stopSerialRead();
		await MixlyWebSerial.target.startSerialRead();
	}
}

MixlyWebSerial.setDtrAndRts = function () {
	if (espTool.connected()) {
		espTool.setDTR($("#set_dtr")[0].checked ?? true);
		espTool.setRTS($("#set_rts")[0].checked ?? true);
	}
}